package com.odata.springboot.starter.odata.utils;

import com.odata.springboot.starter.odata.odata.config.OdataCachedData;
import com.odata.springboot.starter.odata.odata.config.OdataConfig;
import com.odata.springboot.starter.odata.odata.sql.sqlBuild.OdataClassMetaData;
import com.odata.springboot.starter.odata.odata.sql.sqlBuild.OdataSqlInfo;
import com.odata.springboot.starter.odata.odata.sql.sqlBuild.enums.DataBaseProductEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.edm.provider.CsdlEntityType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.*;
import java.util.List;

/**
 * odata jdbc工具类
 * @author chenYX
 * @date 2021/6/30 17:26
 * @description
 */
@Component
@Slf4j
public class OdataJdbcUtils {

    @Autowired
    private OdataConfig odataConfig;

    public  Connection getConnection() throws SQLException {
        return odataConfig.getDataSource().getConnection();
    }

    /**
     * 执行sql 结果姐映射到  List<Entity>
     * @author : yongxiang
     * @description :
     * @param
     * @date : 18:00 2021/6/30
    */
    public  List<Entity> executeSelectSqlAnd2EntityList(OdataSqlInfo odataSqlInfo){
        log.info(String.valueOf(System.currentTimeMillis()));
        try (Connection connection = getConnection()){
            log.info(String.valueOf(System.currentTimeMillis()));
            PreparedStatement preparedStatement = getPreparedStatement(odataSqlInfo, connection);
            ResultSet resultSet = preparedStatement.executeQuery();
            log.info(String.valueOf(System.currentTimeMillis()));
            return OdataEntityUtils.handleMany2EntityList(resultSet, odataSqlInfo.getAClass());
        } catch (Exception e){
            log.error("执行sql语句gg-OdataJdbcUtils.executeSelectSqlAnd2EntityList {}",e.getMessage(),e);
            return null;
        }

    };



    /**
     * 执行sql 结果姐映射到  <Entity>
     * @author : yongxiang
     * @description :
     * @param
     * @date : 11:18 2021/7/1
    */
    public Entity executeSelectSqlAnd2Entity(OdataSqlInfo odataSqlInfo){
        try (Connection connection = getConnection()){
            PreparedStatement preparedStatement = getPreparedStatement(odataSqlInfo, connection);
            ResultSet resultSet = preparedStatement.executeQuery();
            return OdataEntityUtils.handleOne2Entity(resultSet, odataSqlInfo.getAClass());
        } catch (Exception e){
            log.error("执行sql语句gg-OdataJdbcUtils.executeSelectSqlAnd2Entity {}",e.getMessage(),e);
            return null;
        }
    }

    private PreparedStatement getPreparedStatement(OdataSqlInfo odataSqlInfo, Connection connection) throws SQLException {
        String sql = odataSqlInfo.getSql();
        List<Object> args = odataSqlInfo.getParams();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < args.size(); i++) {
            preparedStatement.setObject(i + 1, args.get(i));
        }
        return preparedStatement;
    }

    /**
     * 获取CsdlEntityType
     *
     * @author : yongxiang
     * @description :
     * @param
     * @date : 11:20 2021/7/1
    */
    public CsdlEntityType getEntityTypeByClass(Class<?> aClass){
        //执行
        try(Connection connection = getConnection()) {
            DatabaseMetaData metaData = connection.getMetaData();

            if (OdataCachedData.dataBaseProductEnum == null){
                //初始化数据库类型
                String databaseProductName = metaData.getDatabaseProductName();
                DataBaseProductEnum dataBaseProductEnum = DataBaseProductEnum.getByValueName(databaseProductName);
                if (dataBaseProductEnum != null){
                    OdataCachedData.dataBaseProductEnum = dataBaseProductEnum;
                }
            }

            OdataClassMetaData odataClassMetaData = OdataCachedData.getClassMetaDataByClass(aClass);
            if (odataClassMetaData != null) {
                ResultSet resultSet = metaData.getColumns(null, null, odataClassMetaData.getTableName(), "%");
                return OdataEntityUtils.handleMetaData2EntityType(resultSet, aClass);
            }
            return null;
        } catch (Exception e) {
            log.error("获取 entityType 执行sql失败 {}",e.getMessage(),e);
            return null;
        }

    }


    /**
     * 查询count
     * @author : yongxiang
     * @description :
     * @param
     * @date : 16:00 2021/7/1
    */
    public int executeSelectCount(OdataSqlInfo countSqlInfo) {
        try (Connection connection = getConnection()){
            PreparedStatement preparedStatement = getPreparedStatement(countSqlInfo, connection);
            ResultSet resultSet = preparedStatement.executeQuery();
            if (resultSet.next()){
                return resultSet.getInt(1);
            }
            return 0;
        } catch (Exception e){
            log.error("查询count gg {},sql语句为{}",e.getMessage(),countSqlInfo.getSql(),e);
            return 0;
        }

    }
}
